class Player {
  private readonly _id: string
  private myAudio: HTMLAudioElement
  private states: any
  constructor(id?: string) {
    this._id = id || 'app-audio'
    this.states = {
      label: '',
      run: false,
      active: 0,
      music: {},
      musics: [],
      history: []
    }
    this.createAudio()
  }

  /**
   * 初始化播放器
   */
  private createAudio(): void {
    if (document.getElementById(this._id)) {
      this.myAudio = document.getElementById(this._id) as HTMLAudioElement
      return
    }
    const appAudio = new Audio()
    appAudio.id = this._id || 'app-audio'
    appAudio.src = ''
    appAudio.controls = true
    appAudio.style.display = 'none'
    appAudio.preload = 'metadata'
    appAudio.autoplay = false
    appAudio.addEventListener('error', () => {})
    document.body.appendChild(appAudio)
    this.myAudio = appAudio
  }
  set musics(params: { list: any[]; label: string }) {
    const { list, label } = params
    this.states.musics = list
    this.states.music = list[this.states.active]
    this.states.history.unshift(this.states.music)
    this.states.label = label
    this.myAudio.src = this.states.music[label]
  }
  /**
   * 获取歌曲消息
   */
  get music() {
    return this.states.music
  }

  /**
   * 获取matedata
   */
  public get matedate() {
    const { currentTime, duration } = this.myAudio
    return {
      currentTime: Math.round(currentTime),
      duration: Math.round(duration) || 0
    }
  }
  public onLoadedMetadata(fn: () => unknown) {
    this.myAudio.addEventListener('loadedmetadata', () => {
      fn()
    })
  }
  public onTimeUpdate(fn: () => unknown) {
    this.myAudio.addEventListener('timeupdate', () => {
      fn()
    })
  }

  get history() {
    return [...new Set(this.states.history)]
  }

  /**
   * 获取歌曲列表信息
   * @constructor
   */
  get musicList() {
    return this.states.musics
  }
  get action() {
    return this.states.run
  }
  public circulate(param: () => unknown) {
    // 监听 ended 事件
    this.myAudio.addEventListener('ended', () => {
      // 在这里你可以添加更多的逻辑，比如自动播放下一个音频文件等
      this.next()
      param()
    })
  }
  /**
   * 添加音乐，会将列表清空
   * @param param
   */
  set addMusic(param) {}

  /**
   * 追加音乐
   * @param param
   */
  set appendMusic(param) {}

  /**
   * 播放音乐
   */
  public play() {
    if (!this.states.music) {
      return
    }
    this.states.run = true
    this.myAudio.play().catch((err) => {
      // console.log(err)
    })
  }
  /**
   * 暂停音乐
   */
  public pause(): void {
    if (!this.states.music) {
      return
    }
    this.states.run = false
    this.myAudio.pause()
  }

  /**
   * 单曲循环
   */
  public loop(param: boolean) {
    if (param) {
      this.myAudio.removeEventListener('ended', () => {})
    }
    this.myAudio.loop = param
  }

  /**
   * 静音
   * @param param
   */
  public muted(param: boolean) {
    this.myAudio.muted = param
  }
  // 音量设置
  public volume(param: number) {
    this.myAudio.volume = param/100
  }

  /**
   * 播放下一首
   */
  public next() {
    this.states.run = true
    this.states.active++
    this.states.music = this.states.musics[this.states.active]
    this.myAudio.src = this.states.music[this.states.label]
    if (this.states.active >= this.states.musics.length) {
      this.states.active = 0
    }
    this.play()
    this.states.history.unshift(this.states.music)
  }

  /**
   * 播放上一首
   */
  public prev() {
    this.states.run = true
    this.states.active--
    this.states.music = this.states.musics[this.states.active]
    this.myAudio.src = this.states.music[this.states.label]
    if (this.states.active < 0) {
      this.states.active = Math.max(this.states.musics.length - 1, 0)
    }
    this.play()
    this.states.history.unshift(this.states.music)
  }

  /**
   * 下载
   */
  public download() {
    return this.states.music[this.states.label]
  }

  /**
   * 播放倍速
   */
  public speed() {}

  /**
   * 播放进度
   */
  public updateCurrentTime(param) {
    this.myAudio.currentTime = param
  }
}
export default Player
